package com.miplus.ccrm.core.service;

import com.miplus.ccrm.common.CmdResVo;
import com.miplus.ccrm.common.EnumRCode;
import com.miplus.ccrm.common.JPubUtils;
import com.miplus.ccrm.common.ServiceException;
import com.miplus.ccrm.core.controller.vo.file.UploadResVo;
import com.miplus.ccrm.core.security.JCommonData;
import com.miplus.ccrm.core.service.xsky.XSkyService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.io.File;
import java.time.LocalDate;
import java.util.Date;
import java.util.Random;
import java.util.UUID;

@Slf4j
@Service
public class FileService {
    // 本地上传文件的路径
    @Value("${uploadfiles.path}")
    public String uploadPath;
    // 文件上传方式
    @Value("${uploadfiles.type}")
    private String uploadType;
    @Value("${uploadfiles.filetype}")
    private String uploadFileType;
    @Value("${uploadfiles.filesize}")
    private Integer uploadFileSize;
    @Value("${api.url}")
    private String apiUrl;
    @Value("${nginx.url}")
    private String nginxUrl;
    @Resource
    private XSkyService ossServiceFile;
    @Resource
    private JCommonData jCommonData;

    public UploadResVo doUpload(MultipartFile file) {
        String fileName="";
        if (file.isEmpty()) {
            throw new ServiceException(EnumRCode.FileNull.value, EnumRCode.FileNull.name);
        } else {
            long size = file.getSize(); //校验文件大小
            fileName = file.getOriginalFilename();
            log.info("Upload:fileName={},size={} to {}",fileName,size,uploadType);
            String type = fileName.substring(fileName.lastIndexOf('.') + 1);
            String[] fileType = uploadFileType.split(",");
            if (!Arrays.asList(fileType).contains(type)) {
                throw new ServiceException(EnumRCode.FileTypeErr.value, EnumRCode.FileTypeErr.name);
            } else if (size > 1024 * 1024 * uploadFileSize) {
                throw new ServiceException(EnumRCode.FileSizeOver.value, EnumRCode.FileSizeOver.name);
            }
        }
        UploadResVo resVo=null;
        if(JPubUtils.IsEqual(uploadType,"xsky")){
            resVo = UploadXSky(file);
        }
        else {
            resVo = UploadLocal(file);
        }
        log.info("Upload:fileName={} Done.SetData",fileName);
        //2025-02-13 为了数据安全保存在服务端，url和文件路径值不返回客户端,默认时效60分钟
        UploadResVo rs=new UploadResVo();
        BeanUtils.copyProperties(resVo,rs);
        jCommonData.setData(fileName,rs,3600);

        resVo.setFiledir("");
        resVo.setApiurl("");

        return resVo;
    }

    public UploadResVo UploadLocal(MultipartFile file) {
        UploadResVo uploadResVo=new UploadResVo();
        String fileName = file.getOriginalFilename();   //校验文件名
        try {
            DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyyMMdd");
            String fileDatePath = LocalDate.now().format(dateFormatter);
            File parentPath = new File(uploadPath + "/"+fileDatePath);
            if (!parentPath.exists()) {
                parentPath.mkdir(); //判断父路径是否存在，不存在就创建出来
            }
            Random r = new Random();
            //String newName = new Date().getTime() + r.nextInt(1000) + fileName.substring(fileName.lastIndexOf("."));
            //2023-08-03
            String newName = UUID.randomUUID() + fileName.substring(fileName.lastIndexOf("."));
            log.info("UploadLocal:uploadPath={},apiUrl={},nginxUrl={},newName={}",uploadPath,apiUrl,nginxUrl,newName);
            File newFile = new File(parentPath, newName);
            file.transferTo(newFile);   //复制文件
            String realPath = newFile.getPath();
            String path = "/" + fileDatePath + '/' + newName;

            uploadResVo.setOrifilename(fileName);
            uploadResVo.setFiledir(realPath);
            uploadResVo.setIpaddr(JPubUtils.getLocalIpAddr());
            uploadResVo.setFilename(newName);
            uploadResVo.setApiurl(apiUrl+path);
            if(JPubUtils.IsNotEmpty(nginxUrl)) {
                uploadResVo.setWeburl(nginxUrl + path);
            }
        } catch (Exception e) {
            throw new ServiceException(EnumRCode.FileUploadErr.value,
                    EnumRCode.FileUploadErr.name+":"+e.getMessage()
            );
        }

        return uploadResVo;
    }

    public UploadResVo UploadXSky(MultipartFile file) {
        UploadResVo uploadResVo=new UploadResVo();
        String fileName = file.getOriginalFilename();   //校验文件名
        try {
            DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyyMMdd");
            String fileDatePath = LocalDate.now().format(dateFormatter);
            File parentPath = new File(uploadPath + "/"+fileDatePath);
            if (!parentPath.exists()) {
                parentPath.mkdir(); //判断父路径是否存在，不存在就创建出来
            }
            Random r = new Random();
            //String newName = new Date().getTime() + r.nextInt(1000) + fileName.substring(fileName.lastIndexOf("."));
            //2024-08-03
            String newName = UUID.randomUUID() + fileName.substring(fileName.lastIndexOf("."));
            log.info("UploadLocal:uploadPath={},apiUrl={},nginxUrl={},newName={}",uploadPath,apiUrl,nginxUrl,newName);
            File newFile = new File(parentPath, newName);
            file.transferTo(newFile);   //复制文件
            String realPath = newFile.getPath();
            //String path = "/" + fileDatePath + '/' + newName;

            String newNamesky =newName;// UUID.randomUUID()+ fileName.substring(fileName.lastIndexOf("."));
            log.info("UploadXSky({}):uploadPath={},apiUrl={},nginxUrl={}",newNamesky,uploadPath,apiUrl,nginxUrl);

            ossServiceFile.UploadFile(newNamesky,newFile);

            uploadResVo.setOrifilename(fileName);
            uploadResVo.setFiledir(realPath);
            uploadResVo.setIpaddr(JPubUtils.getLocalIpAddr());
            uploadResVo.setFilename(newNamesky);
            uploadResVo.setApiurl(apiUrl);
            uploadResVo.setWeburl(newNamesky);

            DeleteTemFile(newFile);

            log.info("UploadXSky({}):Done",newNamesky);

        } catch (Exception e) {
            log.error("UploadXsky.Err:",e);
            throw new ServiceException(EnumRCode.FileUploadErr.value,
                    EnumRCode.FileUploadErr.name+":"+e.getMessage()
            );
        }
        return uploadResVo;
    }

    public CmdResVo DownloadFile(String skyid, HttpServletResponse response)
    {
        try {
            ossServiceFile.DownloadFile(skyid,response);
            return new CmdResVo(1,skyid);

        } catch (Exception e) {
            log.error("DownloadFile.Err:",e);
            throw new ServiceException(EnumRCode.FileDownloadErr.value,
                    EnumRCode.FileDownloadErr.name+":"+e.getMessage()
            );
        }
    }
    public CmdResVo DownloadLocalFile(String skyid, HttpServletResponse response)
    {

        log.info("DownloadFile:{}",skyid);

        if(JPubUtils.IsEmpty(skyid)||JPubUtils.IsEqual(skyid,"-1"))
            return new CmdResVo(-1,"没有指定文件名");

        if(skyid.indexOf("../")>=0 || skyid.indexOf("..\\\\")>=0){
            return new CmdResVo(-1,"无效的文件名");
        }
        String filename = uploadPath + skyid;
        log.info("DownloadFileFullName:{}",filename);

        int maxfilesize=1024*1024*uploadFileSize; //50M
        response.addHeader("Content-Type","application/octet-stream;charset=utf-8");
        response.addHeader("Content-Disposition","attachment; filename="+skyid);
        try{
            File file=new File(filename);
            byte[] buf=new byte[1024];
            FileInputStream fis=new FileInputStream(file);
            ServletOutputStream out=response.getOutputStream();
            int len_l=fis.read(buf);
            while (len_l!=-1){
                out.write(buf,0,len_l);
                len_l=fis.read(buf);
            }
            out.flush();
            out.close();
            fis.close();
        }
        catch (Exception e){
            log.error("OnPlayFile.Err:",e);
            throw new ServiceException(EnumRCode.FileDownloadErr.value,
                    EnumRCode.FileDownloadErr.name+":"+e.getMessage());
        }
        return new CmdResVo(1,skyid);
    }
    //2024-08-03
    private void DeleteTemFile(File file)
    {
        try{
            log.info("DeleteTemFile:{}",file.getName());

            file.delete();
        }
        catch (Exception e){
            log.error("DeleteTemFile.Err:",e);
        }
    }
}
